#define _GNU_SOURCE
#include "APP_Serial.h"


//设备串口波特率
int APP_Serial_Baudrate(Device* device,SerialBraudRate baudrate)
{
    //取出termios的全部属性
    struct termios termios_attr;
    int ret = tcgetattr(device->fd,&termios_attr);
    if(ret < 0)
    {
        perror("termios属性取出失败");
        return -1;
    }

    //对属性进行修改
    ret = cfsetspeed(&termios_attr,baudrate);

    //写入属性
    tcsetattr(device->fd,TCSAFLUSH,&termios_attr);

    return 0;
}

//设置串口校验位
static int APP_Serial_Set_Parity(Device* device,SerialParity parity)
{
    //取出termios的全部属性
    struct termios termios_attr;
    int ret = tcgetattr(device->fd,&termios_attr);
    if(ret < 0)
    {
        perror("termios属性取出失败");
        return -1;
    }

    //对属性进行修改
    //设置奇偶校验位
    termios_attr.c_cflag &= ~(PARENB | PARODD); //清除校验位
    termios_attr.c_cflag |= parity; //设置校验位
    //写入属性
    tcsetattr(device->fd,TCSAFLUSH,&termios_attr);

    return 0;
}

//设置串口结束位
static int APP_Serial_Set_Stop(Device* device,SerialStopBits stop)
{
    // 注意设值 检查g成功失败
    // 1 取出termios 的全部属性 get
    struct termios termios_attr;
    int ret = tcgetattr(device->fd,&termios_attr);
    if(ret < 0)
    {
        perror("termios属性取出失败");
        return -1;
    }

    // 2 对属性进行修改
    // 修改停止位
    termios_attr.c_cflag &= ~CSTOPB; // 清除停止位
    termios_attr.c_cflag |= stop; // 设置停止位

    // 3  写入属性 set
    tcsetattr(device->fd, TCSAFLUSH, &termios_attr);
 
}

//设置还原状态
static int APP_Serial_MakeRaw(Device* device)
{
    // 注意设值 检查g成功失败
    // 1 取出termios 的全部属性 get
    struct termios termios_attr;
    int ret = tcgetattr(device->fd,&termios_attr);
    if(ret < 0)
    {
        perror("termios属性取出失败");
        return -1;
    }

    // 2 恢复原始状态
    cfmakeraw(&termios_attr);

    // 3  写入属性 set
    tcsetattr(device->fd, TCSAFLUSH, &termios_attr);
    return 0; 
}

//设置阻塞模式
int APP_Serial_Block(Device* device,int block)
{
    // 1 取出termios 的全部属性 get
    struct termios termios_attr;
    int ret = tcgetattr(device->fd,&termios_attr);
    if(ret < 0)
    {
        perror("termios属性取出失败");
        return -1;
    }

    // 2  设置非阻塞状态
    if (block)
    {
        termios_attr.c_cc[VTIME] = 0; // 死等
        termios_attr.c_cc[VMIN] = 1;  // 至少有几个字符
    }
    else
    {
        termios_attr.c_cc[VTIME] = 2; //  0.2秒  每1=0.1秒
        termios_attr.c_cc[VMIN] = 0;  // 没有也可以
    }

    // 3  写入属性 set
    tcsetattr(device->fd, TCSAFLUSH, &termios_attr); 
}


//给设备初始化串口配置
int APP_Serial_Init(Device* device)
{
    log_info("APP_Serial_Init ");
    //确定当前设备类型
    device->Dev_type = Device_Serial;
    //还原设备配置
    APP_Serial_MakeRaw(device);
    //配置波特率
    APP_Serial_Baudrate(device,BR_115200);
    //配置校验位
    APP_Serial_Set_Parity(device,Parity_None);
    //配置停止位
    APP_Serial_Set_Stop(device,StopBit_One);
    //flush 配置真正刷写到设备中

    int ret = tcflush(device->fd, TCIOFLUSH);
    if(ret ==0)
    {
        log_info("串口配置成功");
    }
    return 0; 
}


